package erfgame.core.world.terrain.insertion;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;


import erfgame.core.Point3D;
import erfgame.core.graphics.renderer.EntityRenderer;
import erfgame.core.graphics.renderer.chain.RendererChain;

public class SurfaceRendererInsertion 
	extends AbstractSurfaceInsertion {
	
	private static final long serialVersionUID = 0;
	
	protected Point3D blockKey;
	
	protected int depth;
	protected int xoff;
	protected int yoff;
	protected RendererChain rendererChain;
	protected Rectangle intersectionBounds;
	protected int renderBoundsY;
	
	protected SurfaceRendererInsertion() {
		
	}
	
	public SurfaceRendererInsertion( int depth, RendererChain rendererChain, int xoff, int yoff, Rectangle intersectionBounds, int renderBoundsY, Point3D blockKey ) {
		this.depth = depth;
		this.rendererChain = rendererChain; 
		this.xoff = xoff;
		this.yoff = yoff;
		this.intersectionBounds = intersectionBounds;
		this.renderBoundsY = renderBoundsY;
		this.blockKey = blockKey;
		if( !blockKey.getClass().equals(Point3D.class)) {
			throw new RuntimeException();
		}
	}
	
	

	@Override
	public boolean contains(int lx, int ly) {
		boolean b;
		if( super.contains(lx, ly) ) {
			int rx = lx - intersectionBounds.x + xoff;
			int ry = ly - intersectionBounds.y + yoff;
			b = rendererChain.getHead().contains(rx, ry);
		} else {
			b = false;
		}
		return b;
	}

	public Rectangle getBounds() {
		return this.intersectionBounds;
	}
	
	public int getXOff() {
		return this.xoff;
	}
	
	public int getYOff() {
		return this.yoff;
	}
	
	public int getDepth() {
		return this.depth;
	}
	
	public EntityRenderer getRenderer() {
		return this.rendererChain.getHead();
	}
	
	public RendererChain getRendererChain() {
		return this.rendererChain;
	}
	
	public int getDepth( Rectangle r ) {
		return depth;
	}

	public int getDepth(Point p) {
		return this.depth;
	}
	
	public Point3D getBlockKey() {
		return blockKey;
	}

	public void render(Graphics g, boolean isTop) {
		Rectangle clip = g.getClipBounds();
		// don't want to clip the top off (due to illusion of depth, will be overwritten by layer above if appropriate)
		int bottom = this.intersectionBounds.y + this.intersectionBounds.height;
		if( isTop ) {
			g.clipRect( this.intersectionBounds.x, clip.y, this.intersectionBounds.width, bottom - clip.y );
		} else {
			g.clipRect( this.intersectionBounds.x, this.renderBoundsY, this.intersectionBounds.width, bottom - this.renderBoundsY );
		}
		this.rendererChain.getHead().render(g, this.intersectionBounds.x - this.xoff, this.intersectionBounds.y - this.yoff );
//		g.setColor( Color.magenta );
//		String s = blockKey.toString();
//		g.drawString(s, this.bounds.x, bounds.y + g.getFontMetrics().getAscent());
//		g.setColor( Color.green );
//		g.drawRect( this.bounds.x, this.bounds.y, this.bounds.width-1, this.bounds.height-1 );
		g.setClip( clip );
	}

	@Override
	public boolean equals(Object obj) {
		if( obj != null && obj.getClass().equals( this.getClass() ) ) {
			return equals( (SurfaceRendererInsertion) obj );
		} else {
			return false;
		}
	}
	
	public boolean equals( SurfaceRendererInsertion i ) {
		// TODO : need to know block that we're in to be able to see if this is equal
		return i.rendererChain.equals( this.rendererChain ) && i.blockKey.equals( this.blockKey );
	}

	@Override
	public int hashCode() {
		return rendererChain.hashCode() + blockKey.hashCode();
	}
}
